package com.apes.fn.server.productReceive;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.server.productReturn.ProductReturnRepository;
import com.apes.fn.server.servicePlan.model.ServicePlanItem;
import com.apes.fn.server.productReturn.ProductReturn;
import com.apes.fn.server.productReturn.ProductReturnItem;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.servicePlan.service.ServicePlanceService;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.Model;
import com.apes.framework.jpa.logger.ApesLoggerService;
import com.apes.framework.jpa.repository.CustomRepository;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.plugin.outbox.OutboxPayloadWrapper;
import com.apes.framework.plugin.outbox.annotation.OutboxSubscriber;
import com.apes.framework.plugin.soe.metadata.BusinessType;
import com.apes.framework.plugin.soe.store.database.repository.BusinessTypeRepository;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.scm.account.account.model.Stock;
import com.apes.scm.account.account.repository.StockRepository;
import com.apes.scm.account.account.service.ProductAccountService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.product.model.Product;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import com.apes.scm.masterdata.product.service.UomService;
import com.apes.scm.masterdata.stock.model.Location;
import com.apes.scm.masterdata.stock.repository.LocationRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.*;

@Service("productReceiveService")
public class ProductReceiveService extends DomainService {

    @Autowired
    ProductReceiveRepository productReceiveRepository;

    @Autowired
    ProductReceiveItemRepository productReceiveItemRepository;

    @Autowired
    ProductAccountService productAccountService;

    @Autowired
    StockRepository stockRepository;

    @Autowired
    ProductRepository productRepository;

    @Autowired
    ProductUomRepository productUomRepository;

    @Autowired
    ServicePlanceService servicePlanceService;

    @Autowired
    ServicePlanItemRepository servicePlanItemRepository;

    /**
     * 创建
     *
     * @param request
     * @return
     */
    public ProductReceive create(SimpleRequest request) {
        ProductReceive productReceive = request.getO(ProductReceive.class);
        checkReceiveRule(productReceive);
        productReceive.setState("create");

//        boolean flag = productReceive.isWrite();

        productReceive = productReceiveRepository.saveAndFlush(productReceive);
//        productReceive.setWrite(flag);
        return productReceive;
    }

    /**
     * 功能: 修改
     *
     * @param request
     * @return
     */
    public ProductReceive update(SimpleRequest request) {
        ProductReceive oldProductReceive = (ProductReceive) isVaild(request, productReceiveRepository);
        ProductReceive productReceive = request.getO(ProductReceive.class);
        checkReceiveRule(productReceive);
        productReceive = productReceiveRepository.saveAndFlush(productReceive);
        return productReceive;
    }

    /**
     * 功能：删除订单
     *
     * @param request
     * @return
     */
    public ProductReceive delete(SimpleRequest request) {
        isVaild(request, productReceiveRepository);
        ProductReceive ProductReceive = request.getO(ProductReceive.class);
        return deleteBase(ProductReceive,getPerson(request));
    }

    private ProductReceive deleteBase(ProductReceive productReceive,PartyRole role){
        productReceive.setState("delete");
        productReceive.setDeleteId(role);
        productReceive.setDeleteDate(new Date());
        return productReceiveRepository.saveAndFlush(productReceive);
    }

    /**
     * 功能：审批订单
     *
     * @param request
     * @return
     */
    public ProductReceive approve(SimpleRequest request) {
        isVaild(request, productReceiveRepository);
        ProductReceive oldProductReceive = request.getO(ProductReceive.class);
        oldProductReceive.setState("approve");
        oldProductReceive.setApproveId(getPerson(request));
        oldProductReceive.setApproveDate(new Date());
        checkReceiveRule(oldProductReceive);
//        boolean flag = oldProductReceive.isWrite();
        ProductReceive productReceive = productReceiveRepository.saveAndFlush(oldProductReceive);

        // 保管数减少 领用在途增加
        updateStock(oldProductReceive, "配件领用单审核");
        // 回写领用数量
        SpringManager.getBean(ServicePlanceService.class).rewriteServicePlanByProductReceive(productReceive,getPerson(request));
//        productReceive.setWrite(flag);
        return productReceive;
    }

    /**
     * 更新库存账
     * 可用数、保管数、领用在途、冻结数
     * @param productReceive 领用单数据
     * @param remarks 备注
     */
    private void updateStock(ProductReceive productReceive, String remarks) {

        productReceive.getProductReceiveItems().stream().forEach(productReceiveItem -> {

            // 冻结数
            productAccountService.setProductFrozen(productReceiveItem.getProduct(), productReceive.getLocation(),
                    productReceiveItem.getUom(), -1 * productReceiveItem.getQtyReceive(),
                    productReceive.getInnerBusinessType(), productReceive.getId(),
                    productReceiveItem.getId(), remarks,productReceive.getCompany(),"ServicePlan",productReceive.getSource(),productReceiveItem.getServicePlanItem().getInnerBusinessKey());

            // 可用数
            productAccountService.setProductAvailable(productReceiveItem.getProduct(),
                    productReceive.getLocation(), productReceiveItem.getUom(), -1 * productReceiveItem.getQtyReceive(),
                    productReceive.getInnerBusinessType(), productReceive.getId(),
                    productReceiveItem.getId(), remarks, productReceive.getCompany());

            // 保管数
            productAccountService.setProductCustody(productReceiveItem.getProduct(),
                    productReceive.getLocation(), productReceiveItem.getUom(), -1 * productReceiveItem.getQtyReceive(),
                    productReceive.getInnerBusinessType(), productReceive.getId(),
                    productReceiveItem.getId(), remarks, productReceive.getCompany());

            // 领用在途
            productAccountService.setProductLend(productReceiveItem.getProduct(),
                    productReceive.getLocation(), productReceive.getReceiver(), productReceiveItem.getUom(),
                    productReceiveItem.getQtyReceive(), "lend", productReceive.getCompany());
        });
    }

    /***
     * 回写服务方案领用数量
     */
    private void addQtyReceive(ProductReceive productReceive) {
        productReceive.getProductReceiveItems().stream().forEach(productReceiveItem -> {
            ServicePlanItem servicePlanItem = productReceiveItem.getServicePlanItem();
            servicePlanItem.addQtyReceive(productReceiveItem.getQtyReceive());
            servicePlanItemRepository.saveAndFlush(servicePlanItem);
        });
    }


    /***
     * 数据是否合法
     * @param request
     * @param repository
     */
    private Model isVaild(SimpleRequest request, CustomRepository repository) {
        Model oldModel = (Model) repository.findOne((String) request.get("id"));
        if (oldModel == null) throw new RuntimeException("订单【" + request.get("id") + "】在系统中不存在。");
        if (oldModel.getVersion() != (int) request.get("version")) throw new RuntimeException("记录已更新或已删除，请重新提交！");
        return oldModel;
    }


    /***
     * 功能：获取实际可用数
     * 1. 修改
     * 2. 新增
     */
    public Map getUsableQtyToUom(SimpleRequest request) {
        Map returnMap = new HashMap();
        JSONObject tempJson = request.getJO();
        Location location = new Location();
        PartyRole company = new PartyRole();
        Product product = productRepository.findOne(tempJson.getJSONObject("product").getString("id"));
        ProductUom uom = productUomRepository.findOne(tempJson.getJSONObject("uom").getLong("id"));
        location.setId(tempJson.getJSONObject("location").getString("id"));
        company.setId(tempJson.getJSONObject("company").getString("id"));

        // 基础计量单位
        ProductUom baseUom = SpringManager.getBean(UomService.class).getUom(company, product);

        // 剩余可用数
        Double restUsableQty = 0.00;
        List<Stock> procductList = stockRepository.findAll(JpaDsl.toCriteria(MapUtil.mapper("location", location, "product", product)));
        if (procductList != null && procductList.size() > 0) restUsableQty = procductList.get(0).getMarketableQty();


        // 已占用可用数
        Double occupyUsableQty = 0.00;
        if (tempJson.get("id") != null) {
            ProductReceiveItem productReceiveItem = productReceiveItemRepository.findOne(tempJson.getString("id"));
            occupyUsableQty = productReceiveItem.getUom().computeQty(productReceiveItem.getQtyReceive(), baseUom, false);
        }
        returnMap.put("marketableQty", baseUom.computeQty(occupyUsableQty + restUsableQty, uom, true));

        return returnMap;
    }

    /***
     * 查询所有能归还的明细
     */
    public List<Map> findAllReturnable(SimpleRequest request) {
        List<Map> cacheList = new ArrayList();
        Location location = request.getO(Location.class);
        List<ProductReceiveItem> productReceiveItems = productReceiveItemRepository.findAllReturnable(location).stream().sorted(
                (a1, a2) -> a1.getProductReceive().getSource().compareTo(a2.getProductReceive().getSource())
        ).collect(Collectors.toList());

        for (ProductReceiveItem item : productReceiveItems) {
            cacheList.add(MapUtil.mapper(
                    "productReceiveItem", MapUtil.mapper("id", item.getId()),
                    "product", item.getProduct(),
                    "uom", item.getUom(),
                    "qtyReturn", 0,
                    "qtyReturnable", item.getQtyReceive() - item.getQtyReturned(),
                    "carLicense", item.queryCarLicense()
            ));
        }
        return cacheList;
    }
    /***
     * 查询本单能归还的明细
     */
    public List<Map> findAllReturnableByPlanId(SimpleRequest request) {
        List<Map> cacheList = new ArrayList();
//        Location location = request.getO(Location.class);
        JSONObject jo = request.getJO();
        String locationId = jo.getString("locationId");
        Location one = SpringManager.getBean(LocationRepository.class).findOne(locationId);
        List<ProductReceiveItem> productReceiveItems = productReceiveItemRepository.findAllReturnableByPlanId(one,jo.getString("planId")).stream().sorted(
                (a1, a2) -> a1.getProductReceive().getSource().compareTo(a2.getProductReceive().getSource())
        ).collect(Collectors.toList());

        for (ProductReceiveItem item : productReceiveItems) {
            cacheList.add(MapUtil.mapper(
                    "productReceiveItem", MapUtil.mapper("id", item.getId()),
                    "product", item.getProduct(),
                    "uom", item.getUom(),
                    "qtyReturn", 0,
                    "qtyReturnable", item.getQtyReceive() - item.getQtyReturned(),
                    "carLicense", item.queryCarLicense()
            ));
        }
        return cacheList;
    }


    /***
     * 获取服务方案可领用的明细
     */
    public List<Object> findAllItemForReceive(SimpleRequest request) {
        // 查看是否存在未审核的领用单

        List<ProductReceive> productReceives = productReceiveRepository.findAll(
                JpaDsl.toCriteriaByEq("source", request.get("id"), "state", "create"));
        if (productReceives.size() > 0)
            throw new RuntimeException("该方案号存在未处理的领用单号，单号：" + productReceives.get(0).getId());

        return servicePlanceService.findAllItemForReceive(request);
    }

    /**
     * 根据商品归还单，回写归还数量
     * @param productReturn
     */
    public void rewriteProductReceiveByProductReceive(ProductReturn productReturn){
        Map groupMap = productReturn.getProductReturnItems().stream().collect(groupingBy((productReturnItem)->{
            return productReturnItem.getProductReceiveItem().getProductReceive().getId();
        }));
        groupMap.forEach((k,v)->{
            List<ProductReturnItem> productReturnItems
                    = new ArrayList<>((Collection<? extends ProductReturnItem>) v);
            ProductReceive productReceive =
                    productReturnItems.stream().findFirst().get().getProductReceiveItem().getProductReceive();

            productReceive.getProductReceiveItems().forEach(productReceiveItem -> {
                productReturnItems.forEach(productReturnItem -> {
                    if(productReceiveItem.getId().equals(productReturnItem.getProductReceiveItem().getId())){
                        double sales = productReceiveItem.getQtyReturned() + productReturnItem.getQtyReturn();
                        productReceiveItem.setQtyReturned(sales);
                        if("RetailOrder".equals(productReturn.getSourceBusinessType()))productReceiveItem.setQtyToSales(productReturnItem.getQtyReturn());
                    }
                });
            });
            productReceiveRepository.saveAndFlush(productReceive);
        });
    }

    /**
     * 检查领用明细是否合理
     */
    public void checkReceiveRule(ProductReceive productReceive){

        Iterator<ProductReceiveItem> iterator = productReceive.getProductReceiveItems().iterator();

        // 删除明细行为零的数据
        while(iterator.hasNext()){
            ProductReceiveItem item = iterator.next();
            if(item.getQtyReceive() == 0) iterator.remove();
        }
        if( productReceive.getProductReceiveItems().size() == 0) throw new RuntimeException("必须存在有效领用，请检查领用数量");
    }

    @OutboxSubscriber(id="pr.delete.deleteByPlanEnd", name="方案终止，删除新增状态的领用单")
    public void deleteByPlanEnd(OutboxPayloadWrapper outboxPayloadWrapper){
        String payload = outboxPayloadWrapper.getPayload();
        JSONArray.parseArray(payload).forEach(item ->{
            ProductReceive productReceive = productReceiveRepository.findOne((String)item);
            if(productReceive.getApproveDate() != null) throw new RuntimeException("方案终止或质检完成终止领用单，领用单状态已经审核");
            productReceive.setRemark(productReceive.getRemark() + "(系统自动删除未审核单据)");
            deleteBase(productReceive,SpringManager.getBean(PartyRoleRepository.class).findOne("yyadmin"));
            SpringManager.getBean(ApesLoggerService.class).sendSynEvent("event:ir.logger.create", MapUtil.mapper("businessType", "ProductReceive",
                    "businessKey", productReceive.getId(), "operate", "删除", "workPostName",null, "operator_id", "9430"));
        });
    }

    /**
     * 入库 -- 根据门店查询所有能归还的领用单
     * LJP
     * @param request
     * @return
     */
    public JSONArray findAllReturn(SimpleRequest request) {
        JSONObject param = request.getJO();
        String deptId = param.getString("deptId");
        String id = param.getString("id");
        List<ProductReceiveItem> productReceiveItems = productReceiveItemRepository.findAllReturn(deptId);
        productReceiveItems = productReceiveItems.stream().collect(
                collectingAndThen(toCollection(() -> new TreeSet<>(comparing(item->item.getProductReceive().getId()))), ArrayList::new));

        List<ProductReceive> productReceives = productReceiveItems.stream().map(item -> item.getProductReceive()).collect(toList());

        if (id != null) {
            if (id.length() == 4) {
                List<ProductReceive> receives = productReceives.stream().filter(e -> e.getSource() != null && id.equals(e.getSource().substring(e.getSource().length() - 4))).collect(toList());
                productReceives = productReceives.stream().filter(e-> id.equals(e.getId().substring(e.getId().length()-4))).collect(Collectors.toList());
                if (receives.size()!= 0) productReceives.addAll(receives);
            }else {
                List<ProductReceive> receives = productReceives.stream().filter(e ->e.getSource() != null && id.equals(e.getSource())).collect(toList());
                productReceives = productReceives.stream().filter(e-> id.equals(e.getId())).collect(Collectors.toList());
                if (receives.size()!= 0) productReceives.addAll(receives);
            }
        }
        return convertProductReceives(productReceives);
    }

    /**
     * 入库 -- 根据门店查询所有能归还的归还单
     * @param request
     * @return
     */
    public Page findAllReturnPage(SimpleRequest request) {
        JSONObject param = request.getJO();
        String deptId = param.getString("deptId");
        String id = param.getString("id");
        List<ProductReceiveItem> productReceiveItems = productReceiveItemRepository.findAllReturn(deptId);
        productReceiveItems = productReceiveItems.stream().collect(
                collectingAndThen(toCollection(() -> new TreeSet<>(comparing(item->item.getProductReceive().getId()))), ArrayList::new));

        List<ProductReceive> productReceives = productReceiveItems.stream().map(item -> item.getProductReceive()).collect(toList());
        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"));
        if (productReceives.size() == 0) return new PageImpl<>(new ArrayList<>(), pageable, 0);
        return new PageImpl<>(convertProductReceives(autoPage(request,productReceives)), pageable, productReceives.size());
    }


    public JSONArray convertProductReceives(List<ProductReceive> productReceives) {
        JSONArray result = new JSONArray();
        productReceives.forEach(productReceive -> {
            JSONObject jsonObject = convertProductReceive(productReceive);
            result.add(jsonObject);
        });
        return result;
    }

    public JSONObject convertProductReceive(ProductReceive productReceive) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id",productReceive.getId());
        jsonObject.put("type","归还");
        jsonObject.put("locationId",productReceive.getLocation().getId());
        jsonObject.put("locationName",productReceive.getLocation().getName());
        jsonObject.put("origin",productReceive.getSource());
        jsonObject.put("originName",productReceive.getSourceBusinessTypeName());
        jsonObject.put("receiver",productReceive.getReceiver().getName());
        jsonObject.put("approveDate",productReceive.getApproveDate().toString());
        List<ProductReceiveItem> productReceiveItems =  productReceive.getProductReceiveItems().stream().filter(item -> item.getQtyReceive()>item.getQtyReturned()).collect(Collectors.toList());

        //明细
        JSONArray items = new JSONArray();
        productReceiveItems.forEach(productReceiveItem -> {
            JSONObject item = new JSONObject();
            item.put("id",productReceiveItem.getId());
            item.put("productId",productReceiveItem.getProduct().getId());
            item.put("productName",productReceiveItem.getProduct().getName());
            item.put("uom",productReceiveItem.getProduct().getUom().getName());
            item.put("carId",productReceiveItem.getServicePlanItem().getServicePlan().getFnCustomerExpand().getCarLicense());
            item.put("servicePlanId",productReceiveItem.getServicePlanItem().getServicePlan().getId());
            item.put("qty",productReceiveItem.getQtyReceive() - productReceiveItem.getQtyReturned());//领用数量-已归还数量
            items.add(item);
        });
        jsonObject.put("items",items);
        return jsonObject;
    }

    /**
     * 入库--配件归还扫码商品
     * @param request
     * @return
     */
    public JSONObject checkProduct(SimpleRequest request) {
        JSONObject param = request.getJO();
        String productId = param.getString("productId");
        String id = param.getString("id");
        ProductReceive productReceive = productReceiveRepository.findOne(id);
        if (productReceive == null) throw new RuntimeException("找不到该配件领用单:"+ id);
        boolean flag = productReceive.getProductReceiveItems().stream().anyMatch(item -> productId.equals(item.getProduct().getId()));
        if (!flag) throw new RuntimeException("该商品和配件领用单没有关联");
        Product product = productRepository.findOne(productId);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("productId",product.getId());
        jsonObject.put("productName",product.getName());
        jsonObject.put("uom",product.getUom().getName());
        return jsonObject;
    }

    /**
     * 入库记录--配件归还
     * @param request
     * @return
     */
    public JSONArray getProductReturns(SimpleRequest request) throws Exception {
        JSONObject param = request.getJO();
        String deptId = param.getString("deptId");
        String id = param.getString("id");
        String startDate = param.getString("startDate");
        String endDate = param.getString("endDate");

        List<Map> condition = new ArrayList<>();
        condition.add(mapper("field","location.depot.dept.id","value",deptId,"operator","EQ"));
        condition.add(mapper("field","state","value","approve","operator","EQ"));

        if (startDate != null && endDate != null) {
            SimpleDateFormat spdf = new SimpleDateFormat("yyyy-MM-dd");
            Date start = spdf.parse(startDate);
            Date end = spdf.parse(endDate);
            condition.add(mapper("field","approveDate","value",start,"operator","GT"));
            condition.add(mapper("field","approveDate","value",end,"operator","LT"));
        }

        ProductReturnRepository productReturnRepository = SpringManager.getBean(ProductReturnRepository.class);
        List<ProductReturn> productReturnList = productReturnRepository.findAll(JpaDsl.toCriteria(condition));

        if (id != null) {
            if (id.length() == 4) {
                List<ProductReturn> returnList = productReturnList.stream().filter(e -> e.getSource() != null && id.equals(e.getSource().substring(e.getSource().length() - 4))).collect(toList());
                productReturnList = productReturnList.stream().filter(e-> id.equals(e.getId().substring(e.getId().length()-4))).collect(Collectors.toList());
                if (returnList.size()!=0) productReturnList.addAll(returnList);
            }else {
                List<ProductReturn> returnList = productReturnList.stream().filter(e -> e.getSource() != null && id.equals(e.getSource())).collect(toList());
                productReturnList = productReturnList.stream().filter(e->id.equals(e.getId())).collect(Collectors.toList());
                if (returnList.size()!=0) productReturnList.addAll(returnList);
            }

        }
        return convertProductReturns(productReturnList);
    }

    public Page getProductReturnsPage(SimpleRequest request) throws Exception {
        JSONObject param = request.getJO();
        String deptId = param.getString("deptId");
        String id = param.getString("id");
        String startDate = param.getString("startDate");
        String endDate = param.getString("endDate");

        List<Map> condition = new ArrayList<>();
        condition.add(mapper("field","location.depot.dept.id","value",deptId,"operator","EQ"));
        condition.add(mapper("field","state","value","approve","operator","EQ"));

        if (startDate != null && endDate != null) {
            SimpleDateFormat spdf = new SimpleDateFormat("yyyy-MM-dd");
            Date start = spdf.parse(startDate);
            Date end = spdf.parse(endDate);
            condition.add(mapper("field","approveDate","value",start,"operator","GT"));
            condition.add(mapper("field","approveDate","value",addDay(end),"operator","LT"));
        }

        ProductReturnRepository productReturnRepository = SpringManager.getBean(ProductReturnRepository.class);
        List<ProductReturn> productReturnList = productReturnRepository.findAll(JpaDsl.toCriteria(condition));

        Pageable pageable = PageRequest.of(request.get("page"), request.get("size"));
        if (productReturnList.size() == 0) return new PageImpl<>(new ArrayList<>(), pageable, 0);
        return new PageImpl<>(convertProductReturns(autoPage(request,productReturnList)), pageable, productReturnList.size());
    }

    public JSONArray convertProductReturns(List<ProductReturn> productReturns) {
        JSONArray result = new JSONArray();
        productReturns.forEach(productReturn -> {
            JSONObject jsonObject = convertProductReturn(productReturn);
            result.add(jsonObject);
        });
        return result;
    }

    public JSONObject convertProductReturn(ProductReturn productReturn) {
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("id",productReturn.getId());
        jsonObject.put("type","配件");
        jsonObject.put("returnQty",productReturn.getProductReturnItems().stream().mapToDouble(ProductReturnItem::getQtyReturn).sum());
        jsonObject.put("locationId",productReturn.getLocation().getId());
        jsonObject.put("locationName",productReturn.getLocation().getName());
        jsonObject.put("origin",productReturn.getSource());
        jsonObject.put("originName",productReturn.getSourceBusinessTypeName());
        jsonObject.put("approve",productReturn.getApproveId()==null?null:productReturn.getApproveId().getName());
        jsonObject.put("approveDate",productReturn.getApproveDate().toString());
        jsonObject.put("operation","配件归还");
        //明细
        JSONArray items = new JSONArray();
        productReturn.getProductReturnItems().forEach(productReturnItem -> {
            JSONObject item = new JSONObject();
            item.put("carId",productReturnItem.getCarLicense());
            item.put("id",productReturnItem.getId());
            item.put("productId",productReturnItem.getProduct().getId());
            item.put("productName",productReturnItem.getProduct().getName());
            item.put("uom",productReturnItem.getProduct().getUom().getName());
            item.put("qty",productReturnItem.getQtyReturn());//归还数量
            Stock stock = stockRepository.findByProductAndLocation(productReturnItem.getProduct(), productReturn.getLocation());
            item.put("usableQty",stock==null?0:stock.getUsableQty());
            item.put("serviceId",productReturnItem.getProductReceiveItem().getServicePlanItem().getServicePlan().getId());
            items.add(item);
        });
        jsonObject.put("items",items);
        return jsonObject;
    }

    /**
     * 入库--配件领用确认归还
     * @param request
     * @return
     */
    public JSONObject createProductReturn(SimpleRequest request) {
        JSONObject param = request.getJO();
        ProductReceive productReceive = productReceiveRepository.findOne(param.getString("id"));
        if (productReceive == null) throw new RuntimeException("找不到该配件领用单："+param.getString("id"));
        List<ProductReceiveItem> productReceiveItems =  productReceive.getProductReceiveItems().stream().filter(item -> item.getQtyReceive()>item.getQtyReturned()).collect(Collectors.toList());
        if (productReceiveItems.size() == 0) throw new RuntimeException("该领用单没有能归还的明细");

        PartyRoleRepository partyRoleRepository = SpringManager.getBean(PartyRoleRepository.class);
        PartyRole creator = partyRoleRepository.findOne(param.getString("creator"));
        if (creator == null) throw new RuntimeException("ERP找不到该制单人");
        ProductReturn productReturn = new ProductReturn();
        productReturn.setCompany(productReceive.getCompany());
        productReturn.setLocation(productReceive.getLocation());
        productReturn.setSource(productReceive.getId());
        productReturn.setSourceBusinessTypeName("配件领用单");
        productReturn.setSourceBusinessType("ProductReceive");
        productReturn.setRemark("App扫码入库");
        productReturn.setCreator(param.getString("creator"));

        JSONArray items = request.getJO().getJSONArray("items");
        List<ProductReturnItem> productReturnItems = new ArrayList<>();
        for (int i = 0; i < items.size(); i++) {
            JSONObject item = items.getJSONObject(i);
            productReceiveItems.forEach(productReceiveItem -> {
                if (item.getString("id").equals(productReceiveItem.getId())) {
                    ProductReturnItem productReturnItem = new ProductReturnItem();
                    productReturnItem.setCompany(productReceive.getCompany());
                    productReturnItem.setProductReceiveItem(productReceiveItem);
                    productReturnItem.setProduct(productReceiveItem.getProduct());
                    productReturnItem.setUom(productReceiveItem.getUom());
                    productReturnItem.setQtyReturn(Double.valueOf(item.getString("qty")));//归还数量
                    productReturnItems.add(productReturnItem);
                }
            });
        }
        productReturn.setProductReturnItems(productReturnItems);

        productReturn = invoke("stock.productReturn.create", productReturn);
        productReturn = invoke("stock.productReturn.approve", mapper("id",productReturn.getId(),"version",productReturn.getVersion()));
        productReturn.setApproveId(creator);
        return convertProductReturn(productReturn);
    }

    public double findProductReturnQty(SimpleRequest request) {
        JSONObject param = request.getJO();
        String deptId = param.getString("deptId");
        Date startDate = param.getDate("startDate");
        Date endDate = param.getDate("endDate");

        Map<String, Object> map = SpringManager.getBean(ProductReturnRepository.class).findProductReturnQty(deptId, startDate, endDate);
        if (map.size() == 0 ) return 0.0;
        return Double.parseDouble(map.get("qtyReturn").toString());
    }

    public double findProductReceiveQty(SimpleRequest request) {
        JSONObject param = request.getJO();
        String deptId = param.getString("deptId");
        Date startDate = param.getDate("startDate");
        Date endDate = param.getDate("endDate");

        Map<String, Object> map = productReceiveRepository.findProductReceiveQty(deptId, startDate, endDate);
        if (map.size() == 0 ) return 0.0;
        return Double.parseDouble(map.get("qtyReceive").toString());
    }

    public List autoPage(SimpleRequest request, List list) {
        int page = request.getJO().getInteger("page");
        int size = request.getJO().getInteger("size");
        List result = new ArrayList<>();
        if (list.size() <= size*(page +1)) {
            result  = list.subList(page*size,list.size());
        }else {
            result  = list.subList(page*size,size*(page +1));
        }
        return result;
    }

    public int waitReturunQty(SimpleRequest request) {
        String deptId = request.getJO().getString("deptId");
        List<ProductReceiveItem> productReceiveItems = productReceiveItemRepository.findAllReturn(deptId);
        productReceiveItems = productReceiveItems.stream().collect(
                collectingAndThen(toCollection(() -> new TreeSet<>(comparing(item->item.getProductReceive().getId()))), ArrayList::new));

        List<ProductReceive> productReceives = productReceiveItems.stream().map(item -> item.getProductReceive()).collect(toList());
        return productReceives.size();
    }

    public Date addDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE,1);
        return cal.getTime();
    }

    /**
     * 根据来源方案查询未审核的配件领用单
     * @param re
     * @return
     */
    public List<ProductReceive> findCreateProductReceive(SimpleRequest re){
        List<ProductReceive> productReceives = productReceiveRepository.findAll(
                JpaDsl.toCriteriaByEq("source", re.getJO().getString("id") , "state", "create"));
        return productReceives.size() > 0 ? productReceives : null;
    }
}
